package com.harmony.pilot.data.service;

import com.harmony.pilot.common.dto.ASTSymbol;
import com.harmony.pilot.common.dto.FunctionImplementation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * 函数实现查询服务
 * 通过CodeQL查找函数实现，提供最佳编码提示
 */
@Service
@Slf4j
public class FunctionImplementationService {
    
    @Value("${codeql.database-path}")
    private String databasePath;
    
    @Value("${codeql.cli-path:codeql}")
    private String cliPath;
    
    /**
     * 根据函数调用查找函数实现
     * 
     * @param functionName 函数名
     * @param qualifiedName 完整限定名（可选）
     * @param contextFilePath 调用上下文文件路径
     * @return 函数实现信息
     */
    @Cacheable(value = "function-implementations", 
               key = "#functionName + ':' + (#qualifiedName != null ? #qualifiedName : '')")
    public FunctionImplementation findFunctionImplementation(
            String functionName, 
            String qualifiedName,
            String contextFilePath) {
        
        log.info("Finding implementation for function: {} (qualified: {})", 
            functionName, qualifiedName);
        
        FunctionImplementation impl = new FunctionImplementation();
        impl.setFunctionName(functionName);
        impl.setQualifiedName(qualifiedName);
        
        try {
            // 1. 使用CodeQL查询函数定义
            ASTSymbol functionSymbol = findFunctionByCodeQL(functionName, qualifiedName, contextFilePath);
            
            if (functionSymbol != null) {
                impl.setSymbol(functionSymbol);
                
                // 2. 读取函数实现代码
                String implementationCode = readFunctionImplementation(
                    functionSymbol.getFilePath(),
                    functionSymbol.getStartLine(),
                    functionSymbol.getEndLine()
                );
                impl.setImplementationCode(implementationCode);
                
                // 3. 查找函数的调用者（了解使用场景）
                List<String> callers = findFunctionCallers(functionName, qualifiedName);
                impl.setCallers(callers);
                
                // 4. 提取函数参数和返回值信息
                extractFunctionDetails(functionSymbol, impl);
                
                log.info("Found implementation for {} at {}:{}", 
                    functionName, functionSymbol.getFilePath(), functionSymbol.getStartLine());
            } else {
                log.warn("Function implementation not found: {}", functionName);
            }
            
        } catch (Exception e) {
            log.error("Failed to find function implementation", e);
        }
        
        return impl;
    }
    
    /**
     * 通过CodeQL查找函数定义
     */
    private ASTSymbol findFunctionByCodeQL(String functionName, String qualifiedName, String contextFilePath) {
        try {
            // 构建CodeQL查询
            String query = buildFunctionQuery(functionName, qualifiedName, contextFilePath);
            
            // 执行查询
            String result = executeCodeQLQuery(query);
            
            // 解析结果（取第一个匹配的函数）
            List<ASTSymbol> symbols = parseFunctionSymbols(result);
            
            if (!symbols.isEmpty()) {
                // 优先选择与上下文文件相关的函数
                ASTSymbol bestMatch = symbols.stream()
                    .filter(s -> contextFilePath != null && 
                               s.getFilePath() != null && 
                               s.getFilePath().contains(contextFilePath))
                    .findFirst()
                    .orElse(symbols.get(0));
                
                return bestMatch;
            }
            
        } catch (Exception e) {
            log.error("Failed to query function from CodeQL", e);
        }
        
        return null;
    }
    
    /**
     * 构建CodeQL查询
     */
    private String buildFunctionQuery(String functionName, String qualifiedName, String contextFilePath) {
        StringBuilder query = new StringBuilder();
        query.append("import cpp\n\n");
        query.append("from Function f\n");
        query.append("where ");
        
        if (qualifiedName != null && !qualifiedName.isEmpty()) {
            // 使用完整限定名查询（更精确）
            query.append("f.getQualifiedName().matches(\"%")
                 .append(escapeQueryString(qualifiedName))
                 .append("%\")\n");
        } else {
            // 使用函数名查询
            query.append("f.getName().matches(\"%")
                 .append(escapeQueryString(functionName))
                 .append("%\")\n");
        }
        
        query.append("select ");
        query.append("f.getName() as name, ");
        query.append("\"Function\" as type, ");
        query.append("f.getQualifiedName() as qualifiedName, ");
        query.append("f.getType() as returnType, ");
        query.append("f.getParameters() as parameters, ");
        query.append("f.getLocation().getStartLine() as startLine, ");
        query.append("f.getLocation().getEndLine() as endLine, ");
        query.append("f.getLocation().getStartColumn() as startColumn, ");
        query.append("f.getLocation().getEndColumn() as endColumn, ");
        query.append("f.getFile().getRelativePath() as filePath\n");
        query.append("limit 10");
        
        return query.toString();
    }
    
    /**
     * 执行CodeQL查询
     */
    private String executeCodeQLQuery(String query) throws Exception {
        File queryFile = File.createTempFile("codeql-function-", ".ql");
        queryFile.deleteOnExit();
        Files.writeString(queryFile.toPath(), query);
        
        ProcessBuilder pb = new ProcessBuilder(
            cliPath,
            "query", "run",
            "--database=" + databasePath,
            "--format=json",
            queryFile.getAbsolutePath()
        );
        
        Process process = pb.start();
        
        StringBuilder output = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
        }
        
        process.waitFor();
        
        if (process.exitValue() != 0) {
            throw new Exception("CodeQL query failed with exit code: " + process.exitValue());
        }
        
        return output.toString();
    }
    
    /**
     * 解析函数符号结果
     */
    private List<ASTSymbol> parseFunctionSymbols(String jsonResult) {
        List<ASTSymbol> symbols = new ArrayList<>();
        
        try {
            // TODO: 使用Jackson解析JSON
            // 简化处理：解析CodeQL的JSON输出
            // CodeQL JSON格式通常是数组，每个元素包含查询结果
            
            // 临时实现：解析CSV格式（如果CodeQL返回CSV）
            String[] lines = jsonResult.split("\n");
            for (String line : lines) {
                if (line.trim().isEmpty() || line.startsWith("#") || line.startsWith("[")) {
                    continue;
                }
                
                ASTSymbol symbol = parseSymbolFromCSV(line);
                if (symbol != null) {
                    symbols.add(symbol);
                }
            }
            
        } catch (Exception e) {
            log.error("Failed to parse function symbols", e);
        }
        
        return symbols;
    }
    
    /**
     * 从CSV行解析符号（临时实现）
     */
    private ASTSymbol parseSymbolFromCSV(String line) {
        try {
            // CodeQL CSV格式：用|分隔
            String[] parts = line.split("\\|");
            if (parts.length >= 5) {
                ASTSymbol symbol = new ASTSymbol();
                symbol.setName(parts[0].trim());
                symbol.setType("Function");
                symbol.setQualifiedName(parts.length > 2 ? parts[2].trim() : parts[0].trim());
                
                // 解析文件路径和行号
                if (parts.length > 5) {
                    String filePath = parts[parts.length - 1].trim();
                    symbol.setFilePath(filePath);
                    
                    // 尝试解析行号
                    try {
                        symbol.setStartLine(Integer.parseInt(parts[parts.length - 2].trim()));
                    } catch (NumberFormatException e) {
                        // 忽略
                    }
                }
                
                return symbol;
            }
        } catch (Exception e) {
            log.debug("Failed to parse CSV line: {}", line, e);
        }
        
        return null;
    }
    
    /**
     * 读取函数实现代码
     */
    private String readFunctionImplementation(String filePath, int startLine, int endLine) {
        try {
            // 构建完整路径
            String fullPath = filePath;
            if (!new File(fullPath).isAbsolute()) {
                // 如果数据库路径包含源文件，尝试从数据库路径推断
                // 这需要根据实际数据库结构调整
                fullPath = Paths.get(databasePath).getParent().resolve(filePath).toString();
            }
            
            if (!Files.exists(Paths.get(fullPath))) {
                log.warn("Function implementation file not found: {}", fullPath);
                return null;
            }
            
            // 读取文件内容
            List<String> lines = Files.readAllLines(Paths.get(fullPath));
            
            // 提取函数实现（从startLine到endLine）
            if (startLine > 0 && endLine > 0 && startLine <= lines.size() && endLine <= lines.size()) {
                StringBuilder code = new StringBuilder();
                for (int i = startLine - 1; i < endLine && i < lines.size(); i++) {
                    code.append(lines.get(i)).append("\n");
                }
                return code.toString();
            }
            
        } catch (Exception e) {
            log.error("Failed to read function implementation from: {}", filePath, e);
        }
        
        return null;
    }
    
    /**
     * 查找函数的调用者
     */
    private List<String> findFunctionCallers(String functionName, String qualifiedName) {
        List<String> callers = new ArrayList<>();
        
        try {
            // 构建查询调用者的CodeQL查询
            String query = buildCallerQuery(functionName, qualifiedName);
            executeCodeQLQuery(query);
            
            // 解析调用者信息
            // TODO: 实现解析逻辑
            
        } catch (Exception e) {
            log.error("Failed to find function callers", e);
        }
        
        return callers;
    }
    
    /**
     * 构建调用者查询
     */
    private String buildCallerQuery(String functionName, String qualifiedName) {
        StringBuilder query = new StringBuilder();
        query.append("import cpp\n\n");
        query.append("from Function f, FunctionCall call\n");
        query.append("where ");
        
        if (qualifiedName != null && !qualifiedName.isEmpty()) {
            query.append("call.getTarget().getQualifiedName().matches(\"%")
                 .append(escapeQueryString(qualifiedName))
                 .append("%\")\n");
        } else {
            query.append("call.getTarget().getName().matches(\"%")
                 .append(escapeQueryString(functionName))
                 .append("%\")\n");
        }
        
        query.append("  and call.getTarget() = f\n");
        query.append("select ");
        query.append("call.getEnclosingFunction().getName() as callerName, ");
        query.append("call.getFile().getRelativePath() as filePath, ");
        query.append("call.getLocation().getStartLine() as line\n");
        query.append("limit 20");
        
        return query.toString();
    }
    
    /**
     * 提取函数详细信息
     */
    private void extractFunctionDetails(ASTSymbol symbol, FunctionImplementation impl) {
        // 解析参数信息
        if (symbol.getParameters() != null) {
            impl.setParameters(parseParameters(symbol.getParameters().toString()));
        }
        
        // 设置返回值类型
        if (symbol.getReturnType() != null) {
            impl.setReturnType(symbol.getReturnType().toString());
        }
    }
    
    /**
     * 解析参数字符串
     */
    private List<String> parseParameters(String parametersStr) {
        List<String> params = new ArrayList<>();
        // 简单的参数解析（实际应该使用更完善的解析器）
        if (parametersStr != null && !parametersStr.isEmpty()) {
            String[] parts = parametersStr.split(",");
            for (String part : parts) {
                String trimmed = part.trim();
                if (!trimmed.isEmpty()) {
                    params.add(trimmed);
                }
            }
        }
        return params;
    }
    
    /**
     * 转义查询字符串
     */
    private String escapeQueryString(String value) {
        if (value == null) {
            return "";
        }
        return value.replace("\"", "\\\"").replace("\\", "\\\\");
    }
}

